namespace GuidGeneratorWPF
{
	using System;
	using System.Diagnostics;
	using System.Runtime.CompilerServices;
	using System.Runtime.InteropServices;
	using System.Threading;
	using System.Windows.Forms;

	public class HotKey : Form
	{
		private short _hotkeyID;
		public const int MOD_ALT = 1;
		public const int MOD_CONTROL = 2;
		public const int MOD_SHIFT = 4;
		public const int MOD_WIN = 8;
		private const uint WM_HOTKEY = 0x312;

		public event EventHandler HotKeyPressed;

		public HotKey()
		{
			base.Visible = false;
			this.CreateHandle();
		}

		[DllImport("kernel32", SetLastError = true)]
		private static extern short GlobalAddAtom(string lpString);
		[DllImport("kernel32", SetLastError = true)]
		private static extern short GlobalDeleteAtom(short nAtom);
		protected virtual void OnHotKeyPressed(object sender, EventArgs e)
		{
			try
			{
				if (this.HotKeyPressed != null)
				{
					this.HotKeyPressed(sender, e);
				}
			}
			catch (Exception exception)
			{
				Debug.WriteLine(exception);
			}
		}

		public void RegisterGlobalHotKey(Keys hotkey, int modifiers)
		{
			try
			{
				string lpString = Thread.CurrentThread.ManagedThreadId.ToString("X8") + "HotKey";
				this._hotkeyID = GlobalAddAtom(lpString);
				if (this._hotkeyID == 0)
				{
					throw new Exception("Unable to generate unique hotkey ID. Error code: " + Marshal.GetLastWin32Error().ToString());
				}
				if (RegisterHotKey(base.Handle, this._hotkeyID, modifiers, (int)hotkey) == 0)
				{
					throw new Exception("Unable to register hotkey. Error code: " + Marshal.GetLastWin32Error().ToString());
				}
			}
			catch (Exception exception)
			{
				Debug.WriteLine(exception);
				this.UnregisterGlobalHotKey();
				throw;
			}
		}

		[DllImport("user32", SetLastError = true)]
		private static extern int RegisterHotKey(IntPtr hwnd, int id, int fsModifiers, int vk);
		public void UnregisterGlobalHotKey()
		{
			if (this._hotkeyID != 0)
			{
				UnregisterHotKey(base.Handle, this._hotkeyID);
				GlobalDeleteAtom(this._hotkeyID);
				this._hotkeyID = 0;
			}
		}

		[DllImport("user32", SetLastError = true)]
		private static extern int UnregisterHotKey(IntPtr hwnd, int id);
		protected override void WndProc(ref Message m)
		{
			base.WndProc(ref m);
			if (m.Msg == 0x312L)
			{
				this.OnHotKeyPressed(this, EventArgs.Empty);
			}
		}
	}
}

